<div class="body" role="main">
            
    <div class="section" id="module-requests.models">
  <div class="section" id="id2">
  <h2>发送请求</h2>
  <p>使用 Requests 发送网络请求非常简单。</p>
  <p>一开始要导入 Requests 模块：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">requests</span>
  </code></pre>
  <p>然后，尝试获取某个网页。本例子中，我们来获取 Github 的公共时间线：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'https://api.github.com/events'</span><span class="p">)</span>
  </code></pre>
  <p>现在，我们有一个名为 <code class="docutils literal"><span class="pre">r</span></code> 的 <a class="reference internal" href="../api.html#requests.Response" title="requests.Response"><code class="xref py py-class docutils literal"><span class="pre">Response</span></code></a>
  对象。我们可以从这个对象中获取所有我们想要的信息。</p>
  <p>Requests 简便的 API 意味着所有 HTTP 请求类型都是显而易见的。例如，你可以这样发送一个
  HTTP POST 请求：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s1">'http://httpbin.org/post'</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key'</span><span class="p">:</span><span class="s1">'value'</span><span class="p">})</span>
  </code></pre>
  <p>漂亮，对吧？那么其他 HTTP 请求类型：PUT，DELETE，HEAD 以及 OPTIONS 又是如何的呢？都是一样的简单：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="s1">'http://httpbin.org/put'</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key'</span><span class="p">:</span><span class="s1">'value'</span><span class="p">})</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="s1">'http://httpbin.org/delete'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">head</span><span class="p">(</span><span class="s1">'http://httpbin.org/get'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">options</span><span class="p">(</span><span class="s1">'http://httpbin.org/get'</span><span class="p">)</span>
  </code></pre>
  <p>都很不错吧，但这也仅是 Requests 的冰山一角呢。</p>
  </div>
  <div class="section" id="url">
  <h2>传递 URL 参数</h2>
  <p>你也许经常想为 URL 的查询字符串(query string)传递某种数据。如果你是手工构建 URL，那么数据会以键/值对的形式置于 URL 中，跟在一个问号的后面。例如， <code class="docutils literal"><span class="pre">httpbin.org/get?key=val</span></code>。
  Requests 允许你使用 <code class="docutils literal"><span class="pre">params</span></code> 关键字参数，以一个字符串字典来提供这些参数。举例来说，如果你想传递
  <code class="docutils literal"><span class="pre">key1=value1</span></code> 和 <code class="docutils literal"><span class="pre">key2=value2</span></code> 到 <code class="docutils literal"><span class="pre">httpbin.org/get</span></code> ，那么你可以使用如下代码：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key1'</span><span class="p">:</span> <span class="s1">'value1'</span><span class="p">,</span> <span class="s1">'key2'</span><span class="p">:</span> <span class="s1">'value2'</span><span class="p">}</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"http://httpbin.org/get"</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
  </code></pre>
  <p>通过打印输出该 URL，你能看到 URL 已被正确编码：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
  <span class="go">http://httpbin.org/get?key2=value2&amp;key1=value1</span>
  </code></pre>
  <p>注意字典里值为 <code class="docutils literal"><span class="pre">None</span></code> 的键都不会被添加到 URL 的查询字符串里。</p>
  <p>你还可以将一个列表作为值传入：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key1'</span><span class="p">:</span> <span class="s1">'value1'</span><span class="p">,</span> <span class="s1">'key2'</span><span class="p">:</span> <span class="p">[</span><span class="s1">'value2'</span><span class="p">,</span> <span class="s1">'value3'</span><span class="p">]}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'http://httpbin.org/get'</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
  <span class="go">http://httpbin.org/get?key1=value1&amp;key2=value2&amp;key2=value3</span>
  </code></pre>
  </div>
  <div class="section" id="id3">
  <h2>响应内容</h2>
  <p>我们能读取服务器响应的内容。再次以 GitHub 时间线为例：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">requests</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'https://api.github.com/events'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">text</span>
  <span class="go">u'[{"repository":{"open_issues":0,"url":"https://github.com/...</span>
  </code></pre>
  <p>Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。</p>
  <p>请求发出后，Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 <code class="docutils literal"><span class="pre">r.text</span></code>
  之时，Requests 会使用其推测的文本编码。你可以找出 Requests 使用了什么编码，并且能够使用
  <code class="docutils literal"><span class="pre">r.encoding</span></code> 属性来改变它：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">encoding</span>
  <span class="go">'utf-8'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="s1">'ISO-8859-1'</span>
  </code></pre>
  <p>如果你改变了编码，每当你访问 <code class="docutils literal"><span class="pre">r.text</span></code> ，Request 都将会使用 <code class="docutils literal"><span class="pre">r.encoding</span></code>
  的新值。你可能希望在使用特殊逻辑计算出文本的编码的情况下来修改编码。比如 HTTP 和 XML
  自身可以指定编码。这样的话，你应该使用 <code class="docutils literal"><span class="pre">r.content</span></code> 来找到编码，然后设置 <code class="docutils literal"><span class="pre">r.encoding</span></code>
  为相应的编码。这样就能使用正确的编码解析 <code class="docutils literal"><span class="pre">r.text</span></code> 了。</p>
  <p>在你需要的情况下，Requests 也可以使用定制的编码。如果你创建了自己的编码，并使用
  <code class="docutils literal"><span class="pre">codecs</span></code> 模块进行注册，你就可以轻松地使用这个解码器名称作为 <code class="docutils literal"><span class="pre">r.encoding</span></code> 的值，
  然后由 Requests 来为你处理编码。</p>
  </div>
  <div class="section" id="id4">
  <h2>二进制响应内容</h2>
  <p>你也能以字节的方式访问请求响应体，对于非文本请求：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">content</span>
  <span class="go">b'[{"repository":{"open_issues":0,"url":"https://github.com/...</span>
  </code></pre>
  <p>Requests 会自动为你解码 <code class="docutils literal"><span class="pre">gzip</span></code> 和 <code class="docutils literal"><span class="pre">deflate</span></code> 传输编码的响应数据。</p>
  <p>例如，以请求返回的二进制数据创建一张图片，你可以使用如下代码：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">PIL</span> <span class="k">import</span> <span class="n">Image</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">io</span> <span class="k">import</span> <span class="n">BytesIO</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">i</span> <span class="o">=</span> <span class="n">Image</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">content</span><span class="p">))</span>
  </code></pre>
  </div>
  <div class="section" id="json">
  <h2>JSON 响应内容</h2>
  <p>Requests 中也有一个内置的 JSON 解码器，助你处理 JSON 数据：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">requests</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'https://api.github.com/events'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
  <span class="go">[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...</span>
  </code></pre>
  <p>如果 JSON 解码失败， <code class="docutils literal"><span class="pre">r.json()</span></code> 就会抛出一个异常。例如，响应内容是 401 (Unauthorized)，尝试访问 <code class="docutils literal"><span class="pre">r.json()</span></code> 将会抛出 <code class="docutils literal"><span class="pre">ValueError:</span> <span class="pre">No</span> <span class="pre">JSON</span> <span class="pre">object</span> <span class="pre">could</span> <span class="pre">be</span> <span class="pre">decoded</span></code> 异常。</p>
  <p>需要注意的是，成功调用 <code class="docutils literal"><span class="pre">r.json()</span></code> 并**不**意味着响应的成功。有的服务器会在失败的响应中包含一个 JSON 对象（比如 HTTP 500 的错误细节）。这种 JSON 会被解码返回。要检查请求是否成功，请使用 <code class="docutils literal"><span class="pre">r.raise_for_status()</span></code> 或者检查 <code class="docutils literal"><span class="pre">r.status_code</span></code> 是否和你的期望相同。</p>
  </div>
  <div class="section" id="id5">
  <h2>原始响应内容</h2>
  <p>在罕见的情况下，你可能想获取来自服务器的原始套接字响应，那么你可以访问 <code class="docutils literal"><span class="pre">r.raw</span></code>。
  如果你确实想这么干，那请你确保在初始请求中设置了 <code class="docutils literal"><span class="pre">stream=True</span></code>。具体你可以这么做：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'https://api.github.com/events'</span><span class="p">,</span> <span class="n">stream</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">raw</span>
  <span class="go">&lt;requests.packages.urllib3.response.HTTPResponse object at 0x101194810&gt;</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">raw</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
  <span class="go">'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'</span>
  </code></pre>
  <p>但一般情况下，你应该以下面的模式将文本流保存到文件：</p>
  <pre><code class="language-python"><span></span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">fd</span><span class="p">:</span>
      <span class="k">for</span> <span class="n">chunk</span> <span class="ow">in</span> <span class="n">r</span><span class="o">.</span><span class="n">iter_content</span><span class="p">(</span><span class="n">chunk_size</span><span class="p">):</span>
          <span class="n">fd</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
  </code></pre>
  <p>使用 <code class="docutils literal"><span class="pre">Response.iter_content</span></code> 将会处理大量你直接使用 <code class="docutils literal"><span class="pre">Response.raw</span></code> 不得不处理的。
  当流下载时，上面是优先推荐的获取内容方式。 Note that <code class="docutils literal"><span class="pre">chunk_size</span></code> can be freely adjusted to a number that
  may better fit your use cases.</p>
  </div>
  <div class="section" id="id6">
  <h2>定制请求头</h2>
  <p>如果你想为请求添加 HTTP 头部，只要简单地传递一个 <code class="docutils literal"><span class="pre">dict</span></code> 给 <code class="docutils literal"><span class="pre">headers</span></code> 参数就可以了。</p>
  <p>例如，在前一个示例中我们没有指定 content-type:</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'https://api.github.com/some/endpoint'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'user-agent'</span><span class="p">:</span> <span class="s1">'my-app/0.0.1'</span><span class="p">}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
  </code></pre>
  <p>注意: 定制 header 的优先级低于某些特定的信息源，例如：</p>
  <ul class="simple">
  <li>如果在 <code class="docutils literal"><span class="pre">.netrc</span></code> 中设置了用户认证信息，使用 <cite>headers=</cite> 设置的授权就不会生效。而如果设置了
  <code class="docutils literal"><span class="pre">auth=</span></code> 参数，``.netrc`` 的设置就无效了。</li>
  <li>如果被重定向到别的主机，授权 header 就会被删除。</li>
  <li>代理授权 header 会被 URL 中提供的代理身份覆盖掉。</li>
  <li>在我们能判断内容长度的情况下，header 的 Content-Length 会被改写。</li>
  </ul>
  <p>更进一步讲，Requests 不会基于定制 header 的具体情况改变自己的行为。只不过在最后的请求中，所有的
  header 信息都会被传递进去。</p>
  <p>注意: 所有的 header 值必须是 <code class="docutils literal"><span class="pre">string</span></code>、bytestring 或者 unicode。尽管传递 unicode
  header 也是允许的，但不建议这样做。</p>
  </div>
  <div class="section" id="post">
  <h2>更加复杂的 POST 请求</h2>
  <p>通常，你想要发送一些编码为表单形式的数据——非常像一个 HTML 表单。要实现这个，只需简单地传递一个字典给 <cite>data</cite> 参数。你的数据字典在发出请求时会自动编码为表单形式：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'key1'</span><span class="p">:</span> <span class="s1">'value1'</span><span class="p">,</span> <span class="s1">'key2'</span><span class="p">:</span> <span class="s1">'value2'</span><span class="p">}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"http://httpbin.org/post"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
  <span class="go">{</span>
  <span class="go">  ...</span>
  <span class="go">  "form": {</span>
  <span class="go">    "key2": "value2",</span>
  <span class="go">    "key1": "value1"</span>
  <span class="go">  },</span>
  <span class="go">  ...</span>
  <span class="go">}</span>
  </code></pre>
  <p>你还可以为 <code class="docutils literal"><span class="pre">data</span></code> 参数传入一个元组列表。在表单中多个元素使用同一 key 的时候，这种方式尤其有效：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">payload</span> <span class="o">=</span> <span class="p">((</span><span class="s1">'key1'</span><span class="p">,</span> <span class="s1">'value1'</span><span class="p">),</span> <span class="p">(</span><span class="s1">'key1'</span><span class="p">,</span> <span class="s1">'value2'</span><span class="p">))</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s1">'http://httpbin.org/post'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
  <span class="go">{</span>
  <span class="go">  ...</span>
  <span class="go">  "form": {</span>
  <span class="go">    "key1": [</span>
  <span class="go">      "value1",</span>
  <span class="go">      "value2"</span>
  <span class="go">    ]</span>
  <span class="go">  },</span>
  <span class="go">  ...</span>
  <span class="go">}</span>
  </code></pre>
  <p>很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个 <code class="docutils literal"><span class="pre">string</span></code> 而不是一个 <code class="docutils literal"><span class="pre">dict</span></code>，那么数据会被直接发布出去。</p>
  <p>例如，Github API v3 接受编码为 JSON 的 POST/PATCH 数据：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">json</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'https://api.github.com/some/endpoint'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'some'</span><span class="p">:</span> <span class="s1">'data'</span><span class="p">}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">payload</span><span class="p">))</span>
  </code></pre>
  <p>此处除了可以自行对 <code class="docutils literal"><span class="pre">dict</span></code> 进行编码，你还可以使用 <code class="docutils literal"><span class="pre">json</span></code> 参数直接传递，然后它就会被自动编码。这是 2.4.2 版的新加功能：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'https://api.github.com/some/endpoint'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'some'</span><span class="p">:</span> <span class="s1">'data'</span><span class="p">}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
  </code></pre>
  </div>
  <div class="section" id="post-multipart-encoded">
  <h2>POST一个多部分编码(Multipart-Encoded)的文件</h2>
  <p>Requests 使得上传多部分编码文件变得很简单：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://httpbin.org/post'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">files</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'file'</span><span class="p">:</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'report.xls'</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">)}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">files</span><span class="o">=</span><span class="n">files</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">text</span>
  <span class="go">{</span>
  <span class="go">  ...</span>
  <span class="go">  "files": {</span>
  <span class="go">    "file": "&lt;censored...binary...data&gt;"</span>
  <span class="go">  },</span>
  <span class="go">  ...</span>
  <span class="go">}</span>
  </code></pre>
  <p>你可以显式地设置文件名，文件类型和请求头：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://httpbin.org/post'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">files</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'file'</span><span class="p">:</span> <span class="p">(</span><span class="s1">'report.xls'</span><span class="p">,</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'report.xls'</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">),</span> <span class="s1">'application/vnd.ms-excel'</span><span class="p">,</span> <span class="p">{</span><span class="s1">'Expires'</span><span class="p">:</span> <span class="s1">'0'</span><span class="p">})}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">files</span><span class="o">=</span><span class="n">files</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">text</span>
  <span class="go">{</span>
  <span class="go">  ...</span>
  <span class="go">  "files": {</span>
  <span class="go">    "file": "&lt;censored...binary...data&gt;"</span>
  <span class="go">  },</span>
  <span class="go">  ...</span>
  <span class="go">}</span>
  </code></pre>
  <p>如果你想，你也可以发送作为文件来接收的字符串：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://httpbin.org/post'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">files</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'file'</span><span class="p">:</span> <span class="p">(</span><span class="s1">'report.csv'</span><span class="p">,</span> <span class="s1">'some,data,to,send</span><span class="se">\n</span><span class="s1">another,row,to,send</span><span class="se">\n</span><span class="s1">'</span><span class="p">)}</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">files</span><span class="o">=</span><span class="n">files</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">text</span>
  <span class="go">{</span>
  <span class="go">  ...</span>
  <span class="go">  "files": {</span>
  <span class="go">    "file": "some,data,to,send\\nanother,row,to,send\\n"</span>
  <span class="go">  },</span>
  <span class="go">  ...</span>
  <span class="go">}</span>
  </code></pre>
  <p>如果你发送一个非常大的文件作为 <code class="docutils literal"><span class="pre">multipart/form-data</span></code> 请求，你可能希望将请求做成数据流。默认下 <code class="docutils literal"><span class="pre">requests</span></code> 不支持, 但有个第三方包 <code class="docutils literal"><span class="pre">requests-toolbelt</span></code> 是支持的。你可以阅读
  <a class="reference external" href="https://toolbelt.rtfd.org">toolbelt 文档</a> 来了解使用方法。</p>
  <p>在一个请求中发送多文件参考 <a class="reference internal" href="advanced.html#advanced"><span class="std std-ref">高级用法</span></a> 一节。</p>
  <div class="admonition- admonition">
  <p class="first admonition-title">警告</p>
  <p class="last">我们强烈建议你用二进制模式(<a class="reference external" href="https://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files">binary mode</a>)打开文件。这是因为 Requests 可能会试图为你提供
  <code class="docutils literal"><span class="pre">Content-Length</span></code> header，在它这样做的时候，这个值会被设为文件的字节数（<em>bytes</em>）。如果用文本模式(text mode)打开文件，就可能会发生错误。</p>
  </div>
  </div>
  <div class="section" id="id7">
  <h2>响应状态码</h2>
  <p>我们可以检测响应状态码：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'http://httpbin.org/get'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">status_code</span>
  <span class="go">200</span>
  </code></pre>
  <p>为方便引用，Requests还附带了一个内置的状态码查询对象：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="n">requests</span><span class="o">.</span><span class="n">codes</span><span class="o">.</span><span class="n">ok</span>
  <span class="go">True</span>
  </code></pre>
  <p>如果发送了一个错误请求(一个 4XX 客户端错误，或者 5XX 服务器错误响应)，我们可以通过
  <a class="reference internal" href="../api.html#requests.Response.raise_for_status" title="requests.Response.raise_for_status"><code class="xref py py-meth docutils literal"><span class="pre">Response.raise_for_status()</span></code></a>
  来抛出异常：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">bad_r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'http://httpbin.org/status/404'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">bad_r</span><span class="o">.</span><span class="n">status_code</span>
  <span class="go">404</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">bad_r</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
  <span class="gt">Traceback (most recent call last):</span>
    File <span class="nb">"requests/models.py"</span>, line <span class="m">832</span>, in <span class="n">raise_for_status</span>
      <span class="k">raise</span> <span class="n">http_error</span>
  <span class="gr">requests.exceptions.HTTPError</span>: <span class="n">404 Client Error</span>
  </code></pre>
  <p>但是，由于我们的例子中 <code class="docutils literal"><span class="pre">r</span></code> 的 <code class="docutils literal"><span class="pre">status_code</span></code> 是 <code class="docutils literal"><span class="pre">200</span></code> ，当我们调用
  <code class="docutils literal"><span class="pre">raise_for_status()</span></code> 时，得到的是：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
  <span class="go">None</span>
  </code></pre>
  <p>一切都挺和谐哈。</p>
  </div>
  <div class="section" id="id8">
  <h2>响应头</h2>
  <p>我们可以查看以一个 Python 字典形式展示的服务器响应头：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">headers</span>
  <span class="go">{</span>
  <span class="go">    'content-encoding': 'gzip',</span>
  <span class="go">    'transfer-encoding': 'chunked',</span>
  <span class="go">    'connection': 'close',</span>
  <span class="go">    'server': 'nginx/1.0.4',</span>
  <span class="go">    'x-runtime': '148ms',</span>
  <span class="go">    'etag': '"e1ca502697e5c9317743dc078f67693f"',</span>
  <span class="go">    'content-type': 'application/json'</span>
  <span class="go">}</span>
  </code></pre>
  <p>但是这个字典比较特殊：它是仅为 HTTP 头部而生的。根据
  <a class="reference external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616</a>，
  HTTP 头部是大小写不敏感的。</p>
  <p>因此，我们可以使用任意大写形式来访问这些响应头字段：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">'Content-Type'</span><span class="p">]</span>
  <span class="go">'application/json'</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'content-type'</span><span class="p">)</span>
  <span class="go">'application/json'</span>
  </code></pre>
  <p>它还有一个特殊点，那就是服务器可以多次接受同一 header，每次都使用不同的值。但 Requests
  会将它们合并，这样它们就可以用一个映射来表示出来，参见
  <a class="reference external" href="http://tools.ietf.org/html/rfc7230#section-3.2">RFC 7230</a>:</p>
  <blockquote>
  <div><p>A recipient MAY combine multiple header fields with the same field name
  into one "field-name: field-value" pair, without changing the semantics
  of the message, by appending each subsequent field value to the combined
  field value in order, separated by a comma.</p>
  <p>接收者可以合并多个相同名称的 header 栏位，把它们合为一个 "field-name: field-value"
  配对，将每个后续的栏位值依次追加到合并的栏位值中，用逗号隔开即可，这样做不会改变信息的语义。</p>
  </div></blockquote>
  </div>
  <div class="section" id="cookie">
  <h2>Cookie</h2>
  <p>如果某个响应中包含一些 cookie，你可以快速访问它们：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://example.com/some/cookie/setting/url'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">cookies</span><span class="p">[</span><span class="s1">'example_cookie_name'</span><span class="p">]</span>
  <span class="go">'example_cookie_value'</span>
  </code></pre>
  <p>要想发送你的cookies到服务器，可以使用 <code class="docutils literal"><span class="pre">cookies</span></code> 参数：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://httpbin.org/cookies'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">cookies</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">cookies_are</span><span class="o">=</span><span class="s1">'working'</span><span class="p">)</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="n">cookies</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">text</span>
  <span class="go">'{"cookies": {"cookies_are": "working"}}'</span>
  </code></pre>
  <p>Cookie 的返回对象为 <a class="reference internal" href="../api.html#requests.cookies.RequestsCookieJar" title="requests.cookies.RequestsCookieJar"><code class="xref py py-class docutils literal"><span class="pre">RequestsCookieJar</span></code></a>，它的行为和字典类似，但接口更为完整，适合跨域名跨路径使用。你还可以把 Cookie Jar 传到 Requests 中：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">jar</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">RequestsCookieJar</span><span class="p">()</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">jar</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s1">'tasty_cookie'</span><span class="p">,</span> <span class="s1">'yum'</span><span class="p">,</span> <span class="n">domain</span><span class="o">=</span><span class="s1">'httpbin.org'</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s1">'/cookies'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">jar</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="s1">'gross_cookie'</span><span class="p">,</span> <span class="s1">'blech'</span><span class="p">,</span> <span class="n">domain</span><span class="o">=</span><span class="s1">'httpbin.org'</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s1">'/elsewhere'</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://httpbin.org/cookies'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">cookies</span><span class="o">=</span><span class="n">jar</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">text</span>
  <span class="go">'{"cookies": {"tasty_cookie": "yum"}}'</span>
  </code></pre>
  </div>
  <div class="section" id="id9">
  <h2>重定向与请求历史</h2>
  <p>默认情况下，除了 HEAD, Requests 会自动处理所有重定向。</p>
  <p>可以使用响应对象的 <code class="docutils literal"><span class="pre">history</span></code> 方法来追踪重定向。</p>
  <p><a class="reference internal" href="../api.html#requests.Response.history" title="requests.Response.history"><code class="xref py py-attr docutils literal"><span class="pre">Response.history</span></code></a> 是一个
  <a class="reference internal" href="../api.html#requests.Response" title="requests.Response"><code class="xref py py-class docutils literal"><span class="pre">Response</span></code></a> 对象的列表，为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。</p>
  <p>例如，Github 将所有的 HTTP 请求重定向到 HTTPS：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'http://github.com'</span><span class="p">)</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">url</span>
  <span class="go">'https://github.com/'</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">status_code</span>
  <span class="go">200</span>
  
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">history</span>
  <span class="go">[&lt;Response [301]&gt;]</span>
  </code></pre>
  <p>如果你使用的是GET、OPTIONS、POST、PUT、PATCH 或者 DELETE，那么你可以通过 <code class="docutils literal"><span class="pre">allow_redirects</span></code>
  参数禁用重定向处理：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'http://github.com'</span><span class="p">,</span> <span class="n">allow_redirects</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">status_code</span>
  <span class="go">301</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">history</span>
  <span class="go">[]</span>
  </code></pre>
  <p>如果你使用了 HEAD，你也可以启用重定向：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">head</span><span class="p">(</span><span class="s1">'http://github.com'</span><span class="p">,</span> <span class="n">allow_redirects</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">url</span>
  <span class="go">'https://github.com/'</span>
  <span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="o">.</span><span class="n">history</span>
  <span class="go">[&lt;Response [301]&gt;]</span>
  </code></pre>
  </div>
  <div class="section" id="id10">
  <h2>超时</h2>
  <p>你可以告诉 requests 在经过以 <code class="docutils literal"><span class="pre">timeout</span></code> 参数设定的秒数时间之后停止等待响应。基本上所有的生产代码都应该使用这一参数。如果不使用，你的程序可能会永远失去响应：</p>
  <pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'http://github.com'</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mf">0.001</span><span class="p">)</span>
  <span class="gt">Traceback (most recent call last):</span>
    File <span class="nb">"&lt;stdin&gt;"</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
  <span class="gr">requests.exceptions.Timeout</span>: <span class="n">HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)</span>
  </code></pre>
  <div class="admonition- admonition">
  <p class="first admonition-title">注意</p>
  <p class="last"><code class="docutils literal"><span class="pre">timeout</span></code> 仅对连接过程有效，与响应体的下载无关。 <code class="docutils literal"><span class="pre">timeout</span></code> 并不是整个下载响应的时间限制，而是如果服务器在 <code class="docutils literal"><span class="pre">timeout</span></code> 秒内没有应答，将会引发一个异常（更精确地说，是在
  <code class="docutils literal"><span class="pre">timeout</span></code> 秒内没有从基础套接字上接收到任何字节的数据时）If no timeout is specified explicitly, requests do
  not time out.</p>
  </div>
  </div>
  <div class="section" id="id11">
  <h2>错误与异常</h2>
  <p>遇到网络问题（如：DNS 查询失败、拒绝连接等）时，Requests 会抛出一个
  <code class="xref py py-exc docutils literal"><span class="pre">ConnectionError</span></code> 异常。</p>
  <p>如果 HTTP 请求返回了不成功的状态码， <a class="reference internal" href="../api.html#requests.Response.raise_for_status" title="requests.Response.raise_for_status"><code class="xref py py-meth docutils literal"><span class="pre">Response.raise_for_status()</span></code></a>
  会抛出一个 <code class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></code> 异常。</p>
  <p>若请求超时，则抛出一个 <code class="xref py py-exc docutils literal"><span class="pre">Timeout</span></code> 异常。</p>
  <p>若请求超过了设定的最大重定向次数，则会抛出一个 <code class="xref py py-exc docutils literal"><span class="pre">TooManyRedirects</span></code> 异常。</p>
  <p>所有Requests显式抛出的异常都继承自 <code class="xref py py-exc docutils literal"><span class="pre">requests.exceptions.RequestException</span></code> 。</p>
  <hr class="docutils">
  </div>
  </div>
  
  
            <div id="rtd-o510oasz" class="ethical-alabaster"></div></div>